package com.powernode.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.constant.ManagerConstants;
import com.powernode.domain.SysMenu;
import com.powernode.ex.handler.BusinessException;
import com.powernode.mapper.SysMenuMapper;
import com.powernode.service.SysMenuService;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author 贺
* @description 针对表【sys_menu(菜单管理)】的数据库操作Service实现
* @createDate 2024-07-16 19:35:11
*/
@Service
@CacheConfig(cacheNames = "com.powernode.service.impl.SysMenuServiceImpl")
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu>
    implements SysMenuService{

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Override
    @Cacheable(key = "#loginUserId")
    public Set<SysMenu> queryUserMenuListByUserId(Long loginUserId) {
        Set<SysMenu> menus = sysMenuMapper.selectUserMenuListByUserId(loginUserId);
        // 将菜单集合转换为树形结构
        return transformTree(menus, 0L);
    }

    /**
     * 查询系统所有权限
     *
     * @return
     */
    @Override
    @Cacheable(key = ManagerConstants.SYS_ALL_MENU_KEY)
    public List<SysMenu> queryAllSysMenuList() {
        // 系统的权限集合之间同样有层级关系，但是这里与前端约定，除了登录后的系统菜单集合由后端转为树形结构，其余有层级结构的集合数据都由前端转为树形结构
        return sysMenuMapper.selectList(null);
    }

    /**
     * 新增权限
     *
     * @param sysMenu
     * @return
     */
    @Override
    @CacheEvict(allEntries = true)
    public Boolean saveSysMenu(SysMenu sysMenu) {
        return sysMenuMapper.insert(sysMenu) > 0;
    }

    /**
     * 修改权限
     *
     * @param sysMenu
     * @return
     */
    @Override
    @CacheEvict(allEntries = true)
    public Boolean modifySysMenu(SysMenu sysMenu) {
        // 获取菜单类型
        Integer type = sysMenu.getType();
        // 前端无法将非目录菜单改为目录，后端判断如果传来的菜单类型为目录，则将父节点ID设置为0
        if (0 == type) {
            sysMenu.setParentId(0L);
        }
        return sysMenuMapper.updateById(sysMenu) > 0;
    }

    /**
     * 删除权限
     * 如果当前菜单有子节点，则不能删除
     *
     * @param menuId
     * @return
     */
    @Override
    @CacheEvict(allEntries = true)
    public Boolean removeSysMenuByMenuId(Long menuId) {
        // 根据权限ID查询子菜单集合
        List<SysMenu> sysMenuList = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, menuId));
        // 判断子菜单集合是否为空
        if (CollectionUtil.isNotEmpty(sysMenuList) && sysMenuList.size() > 0) {
            // 待删除的菜单包含子节点，不能删除
            throw new BusinessException("待删除的菜单包含子节点，不能删除");
        }
        // 待删除菜单不包含字节，可以删除
        return sysMenuMapper.deleteById(menuId) > 0;
    }


    /**
     * 将集合转换为树形结构
     * 1. 已知树形结构深度 <= 2
     * 2. 未知树形结构深度
     * @param menus
     * @param pid
     * @return
     */
    private Set<SysMenu> transformTree(Set<SysMenu> menus, long pid) {
        // 1. 已知树形结构深度 <= 2
        /*// 从集合中获取根节点集合（pid=0的元素集合）
        Set<SysMenu> roots = menus.stream().filter(menu -> menu.getParentId().equals(pid)).collect(Collectors.toSet());
        // 遍历根节点集合，将根节点的子节点集合获取出来
        roots.forEach(root -> {
            // 获取当前根节点的子节点集合
            Set<SysMenu> children = menus.stream().filter(menu -> menu.getParentId().equals(root.getMenuId())).collect(Collectors.toSet());
            // 将子节点集合设置到根节点中
            root.setList(children);
        });*/


        // 2. 未知树形结构深度
        // 从集合中获取根节点集合（pid=0的元素集合）
        Set<SysMenu> roots = menus.stream().filter(menu -> menu.getParentId().equals(pid)).collect(Collectors.toSet());
        // 遍历根节点集合
        roots.forEach(r -> r.setList(transformTree(menus, r.getMenuId())));
        return roots;
    }
}




